#include <autoconfig.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include <sys/ioctl.h>


#include <assert.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <stdio.h>

#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdlib.h>


#include "fpga-common.h"

static void send_data_by_spi(int fd, char *buf, int len)
{
    int nbytes     = 0;
    int nsendbytes = 0;
    while (nsendbytes < len)
    {
	nbytes = write(fd, buf + nsendbytes, len - nsendbytes);
	if (nbytes < 0)
	{
	    usleep(1);  // 1us
	    continue;
	}
	nsendbytes += nbytes;
    }
}

static void read_data_by_spi(int fd, char *buf, int len)
{
    int nbytes     = 0;
    int nreadbytes = 0;
    while (nreadbytes < len)
    {
	nbytes = read(fd, buf + nreadbytes, len - nreadbytes);
	if (nbytes < 0)
	{
	    usleep(1);  // 1us
	    continue;
	}
	nreadbytes += nbytes;
    }
}

unsigned int __fpga_transfer(struct fpga_dev *dev, unsigned char cmd, char *tbuf, int tlen, char *rbuf, int rlen, int wait)
{
    /*
    防止 struct fpga_2016 被编译器 n字节对齐，导致长度大于MIN_TX_PACK_SIZE
    末尾的 unsigned short 是校验码
    */
    memset(rbuf, 0xbb, rlen);
    assert(sizeof(struct fpga_2016) + sizeof(unsigned short) == MIN_TX_PACK_SIZE);
    // WDG_CLEAR();

    char              tx_head[sizeof(struct fpga_2016)];
    struct fpga_2016 *ptx   = (struct fpga_2016 *)tx_head;
    unsigned short    cksum = 0;

    ptx->head[0] = 'G', ptx->head[1] = 'L', ptx->head[2] = 'I', ptx->head[3] = 'N', ptx->head[4] = 'K';
    ptx->unuse0 = 0;
    ptx->unuse1 = 0;
    ptx->addr   = 0;
    ptx->len    = 10 + tlen;
    ptx->cmd    = cmd;
    cksum       = cmd;
    cksum += _tx_checksum((uint8_t *)tbuf, tlen);


    if (env_dbg_tx) {
	printf("*****************************");
	_show_cmd_name(cmd);
	printf("tx: %d byte", sizeof(struct fpga_2016));
	PrintfMemory((uint8_t *)tx_head, sizeof(struct fpga_2016));
	printf("buf: %d byte", tlen);
	PrintfMemory((uint8_t *)tbuf, tlen);
	printf("cksum: %d byte", 2);
	PrintfMemory((uint8_t *)&cksum, 2);
    }


    char tx_buf[256] = { 0 };
    memcpy(tx_buf, tx_head, sizeof(tx_head));
    memcpy(tx_buf + sizeof(tx_head), tbuf, tlen);
    memcpy(tx_buf + sizeof(tx_head) + tlen, &cksum, 2);

    send_data_by_spi(dev->fd, tx_buf, tlen + 10);
    usleep(wait);
    // sleep(1);
    read_data_by_spi(dev->fd, rbuf, rlen);

    if (env_dbg_rx) {
	if (rlen > 64) {
	    rlen = 64;
	}
	PrintfMemory((uint8_t *)rbuf, rlen);
    }

    return -1;
}
